
#include "object-oriented.h"
/**
 *  面向对象
*/

/**
 *  内存四区   全局区
*/
// 全局变量
int c = 10;
int d = 10;
const int g_e = 10; //全局常量
const int g_f = 10; //全局常量
void object_test1()
{
    //    全局区
    // 全局变量，静态变量，常量

    // 创建局部变量
    int a = 10;
    int b = 10;

    cout << (int)&a << endl;
    cout << (int)&b << endl;

    cout << (int)&c << endl;
    cout << (int)&d << endl;

    // 静态变量  在普通变量前面加static 属于静态变量
    static int s_a = 10;
    static int s_b = 10;

    cout << (int)&s_a << endl;
    cout << (int)&s_b << endl;

    // 常亮
    // 字符串常亮
    cout << (int)&"asdasdsad" << endl;

    // const 修饰的变量
    // const 修饰的全局变量
    cout << (int)&g_e << endl;
    cout << (int)&g_f << endl;

    const int aaa = 10;
    cout << (int)&aaa << endl;
}

/**
 *  内存四区   栈区
 *  注意事项  不要反悔局部变量的地址
 *  形参也会放在栈上
*/
int *object_test2()
{
    int a = 10; //局部变量 存放在栈区，栈区的数据在函数执行后自动释放
    return &a;  //返回地址
}

/**
 *  内存四区   堆区
 *  程序员管理
*/
int *object_test3()
{
    // 指针本地也是局部变量，放在栈上，数据在堆区
    int *p = new int(10); //利用new关键字可以将数据开辟到 堆区
    return p;
}
void object_test3_1()
{
    // 在堆区开辟数据
    int *p = object_test3();
    cout << *p << endl;
    cout << *p << endl;
    cout << *p << endl;
    delete p;
    // cout << *p << endl;     //内存已经被释放  再次访问会报错
}
void object_test4()
{
    // 创建10个整形数据的数组，在堆区
    int *arr = new int[10];

    // 释放堆区数组  要加上[]
    delete[] arr;
}

/**
 * 1.引用必须初始化
 * 2.引用初始化后，不可以改变
 * 
*/
void object_test5()
{
    // 引用：给变量起别名
    int a = 10;
    int &b = a; //变量b指向的地址是一个
    // int &b;              //报错
    b = 20;
    cout << a << endl;
}

/**
 *  引用做函数参数
 * 
*/
void SetTest(int &a)
{
    a = 20;
}
void object_test6()
{
    int a = 10;
    SetTest(a);
    cout << a << endl;
}

// 引用的本质
// 引用的本质在c++内部实现是一个指针常量

/**
 *  常量引用
 *  使用场景：用来修饰形参，防止误操作
*/
void object_test7()
{
    int a = 10;
    const int &ref = 10;
}

/**
 ** 函数占位参数
 ** 返回值类型 函数名 (占位参数){}  
*/
// 目前来说，可能用不到
void object_test8_func(int a, int)
{
    cout << "" << endl;
}
void object_test8()
{
    object_test8_func(10, 10);
}

//todo 函数重载
//* 1.在同一个作用域下
//* 2.函数名称相同
//* 3.函数参数不同，或者个数不同，或者顺序不同
//* 函数的返回值不可以作为函数重载的条件
//* 注意事项：
//* 1.引用作为重载的条件

void object_test9_func()
{
    cout << "1" << endl;
}
void object_test9_func(int a)
{
    cout << "2" << endl;
}
void object_test9_func(double a)
{
    cout << "3" << endl;
}
void object_test9_func(int a, double b)
{
    cout << "3" << endl;
}
void object_test9_func(double a, int b)
{
    cout << "3" << endl;
}
void object_test9()
{
    object_test9_func();
    object_test9_func(1);
    object_test9_func(3.14);
    object_test9_func(1, 3.14);
    object_test9_func(3.14, 1);
}

//todo 构造函数和析构函数
//* 1.对象初始化清理
//* 1.对象在销毁前 会自动调用析构函数，并且只会调用一次
void object_test10()
{
    class Person
    {
    private:
    public:
        int age;
        Person()
        {
        }
        Person(int a)
        {
            age = a;
        }
        Person(const Person &p) //拷贝构造函数
        {
            age = p.age;
        }
        ~Person() //析构函数 （相当于销毁）
        {
        }
    };

    // 1.括号法
    Person p1;     //默认构造函数
    Person p2(10); //有参构造函数
    Person p3(p2); //拷贝构造函数

    cout << p2.age << endl;
    cout << p3.age << endl;

    // 注意事项
    // 调用默认构造函数时候，不要加()
    // Person p1() ,编译器会认为是一个函数声明，不会认为在创建对象

    // 2.显示法
    Person p4 = Person();
    Person p5 = Person(10);
    Person p6 = Person(p5);

    // Person(10); //匿名对象 特点：当前执行结束后，会被系统立即释放
    // 不要利用拷贝构造函数初始化匿名对象 编译器会认为 Person (p3)===Person p3
    // Person (p6);

    // 隐式转换法
    Person p7 = 10; //相当于 谢了   Person p7 = Person(10) 有参构造
    Person p8 = p7;
}


//todo 拷贝构造函数调用时机
//* 2.值传递方式给函数参数传值
//* 3.值方式返回局部对象
void object_test11(){



    
}